package com.example.backspring.config;

import java.util.concurrent.atomic.AtomicLong;

public class SnowflakeSixDigits {

    // 起始时间戳（2024-09-30 的时间戳）
    private final long twepoch = 1696012800000L;
    // 数据中心 ID 和机器 ID
    private final long datacenterId = 0L;
    private final long workerId = 0L;
    // 每一部分占用的位数
    private final long sequenceBits = 12L;
    private final long workerIdBits = 5L;
    private final long datacenterIdBits = 5L;
    // 最大的序列号和机器 ID、数据中心 ID
    private final long maxSequence = -1L ^ (-1L << sequenceBits);
    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
    private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
    // 序列号、上一次时间戳、当前时间戳
    private long sequence = 0L;
    private long lastTimestamp = -1L;
    private final AtomicLong id = new AtomicLong(0L);

    public synchronized long nextId() {
        long timestamp = timeGen();
        if (timestamp < lastTimestamp) {
            throw new RuntimeException("时钟回拨异常");
        }
        if (lastTimestamp == timestamp) {
            sequence = (sequence + 1) & maxSequence;
            if (sequence == 0) {
                timestamp = tilNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0L;
        }
        lastTimestamp = timestamp;
        long id = ((timestamp - twepoch) << (workerIdBits + datacenterIdBits + sequenceBits)) |
                (datacenterId << (workerIdBits + sequenceBits)) |
                (workerId << sequenceBits) |
                sequence;
        return id;
    }

    private long timeGen() {
        return System.currentTimeMillis();
    }

    private long tilNextMillis(long lastTimestamp) {
        long timestamp = timeGen();
        while (timestamp <= lastTimestamp) {
            timestamp = timeGen();
        }
        return timestamp;
    }

    public static void main(String[] args) {
        SnowflakeSixDigits snowflake = new SnowflakeSixDigits();
        long id = snowflake.nextId();
        // 取后六位数字
        long sixDigitsId = id % 100000000;
        System.out.println(sixDigitsId);
    }
}